package com.bby.user.manager;

import com.alibaba.fastjson.JSON;
import com.bby.common.config.GlobalSettings;
import com.bby.common.exception.BBYException;
import com.bby.common.model.*;
import com.bby.common.utils.StatusCode;
import com.bby.user.bean.UserInfo;
import com.bby.user.bean.UserPubsVO;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Projections;
import com.mongodb.client.model.UpdateOptions;
import com.mongodb.client.model.Updates;
import com.mongodb.client.result.UpdateResult;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.json.JsonWriterSettings;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static com.mongodb.client.model.Filters.eq;
import static com.mongodb.client.model.Filters.regex;
import static org.springframework.data.mongodb.core.query.Criteria.where;
@Component
public class UserActionManager {
    private final MongoTemplate mongoTemplate;
    public static String BUSINESS_COLLECTION = "userBusinessInfo";
    public static String CUSTOM_COLLECTION = "userCustomInfo";

    public UserActionManager(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }
    public UserPubsVO searchUser(String regex, int page, int limit){
        Query query = new Query(where("username")
                .regex(regex,"i"));
        long total = -1;
        if (page==1){// 第一页统计
            total = mongoTemplate.count(query.limit(GlobalSettings.MAX_SEARCH_LIMIT),CUSTOM_COLLECTION);
        }else {
            query = query.skip(((long) (page - 1)) * limit);
        }
        List<UserPublicInfo> list = mongoTemplate.find(query.limit(limit),UserCustomInfo.class)
                .stream()
                .map(UserPublicInfo::new)
                .collect(Collectors.toList());
        return new UserPubsVO(total,list);
    }

    public List<UserGroup> getUserGroup(String userId) throws BBYException {
        Bson query = eq("_id",new ObjectId(userId));
        Document document = mongoTemplate.getCollection(BUSINESS_COLLECTION)
                .find(query)
                .projection(Projections.include("userGroups"))
                .first();
        if (document==null){
            throw new BBYException(StatusCode.USER_NOT_FOUND,"用户不存在");
        }
        UserBusinessInfo businessInfo = JSON.parseObject(
                document.toJson(JsonWriterSettings.builder().build()),
                UserBusinessInfo.class);
        return businessInfo.getUserGroups();
    }
    public List<FavoriteGroup> getFavorites(String userId) throws BBYException {
        Bson query = eq("_id",new ObjectId(userId));
        Document document = mongoTemplate.getCollection(BUSINESS_COLLECTION)
                .find(query)
                .projection(Projections.include("favorites"))
                .first();
        if (document==null){
            throw new BBYException(StatusCode.USER_NOT_FOUND,"用户不存在");
        }
        UserBusinessInfo businessInfo = JSON.parseObject(
                document.toJson(JsonWriterSettings.builder().build()),
                UserBusinessInfo.class);
        return businessInfo.getFavorites();
    }

    private void checkUserGroupName(String userId, String name) throws BBYException {
        Query query = new Query(where("_id").is(userId)
                .andOperator(where("userGroups.name").is(name)));
        if (mongoTemplate.exists(query,BUSINESS_COLLECTION)){
            throw new BBYException(StatusCode.ALREADY_EXIST,"用户组已存在！");
        }
    }
    // 用户组
    public void addUserGroup(String userId, UserGroup userGroup) throws BBYException {
        checkUserGroupName(userId,userGroup.getName());
        Query query = new Query(where("_id").is(userId));
        Update update = new Update().addToSet("userGroups",userGroup);
        mongoTemplate.updateFirst(query,update,BUSINESS_COLLECTION);
    }
    public void renameUserGroup(String userId, String groupId, String newName) throws BBYException {
        checkUserGroupName(userId,newName);
        Query query = new Query(where("_id").is(userId)
                .andOperator(where("userGroups._id").is(groupId)));
        if (!mongoTemplate.exists(query,BUSINESS_COLLECTION)){
            throw new BBYException(StatusCode.NOT_FOUND,"分组没找着！");
        }
        Update update = new Update().set("userGroups.$.name", newName);
        mongoTemplate.updateFirst(query,update,BUSINESS_COLLECTION);
    }
    public void addUserToGroup(String userId, String groupId,String value) throws BBYException {
        Query query = new Query(where("userGroups._id").is(groupId)
                .andOperator(where("_id").is(userId)));
        if (!mongoTemplate.exists(query,BUSINESS_COLLECTION)){
            throw new BBYException(StatusCode.NOT_FOUND,"分组没找着！");
        }
        Update update = new Update().addToSet("userGroups.$.content",value);
        UpdateResult result = mongoTemplate.updateFirst(query,update,BUSINESS_COLLECTION);
        if (result.getMatchedCount()==0){
            throw new BBYException(StatusCode.NOT_FOUND,"分组没找着");
        }
        if (result.getModifiedCount()==0){
            throw new BBYException(StatusCode.FILE_ALREADY_EXIST,"用户已在分组中！");
        }
    }
    public void deleteUserGroup(String userId, String groupId) throws BBYException {
        Query query = new Query(where("_id").is(userId));
        Document doc = new Document();
        doc.put("_id",groupId);
        Update update = new Update().pull("userGroups", doc);
        UpdateResult result = mongoTemplate.updateFirst(query,update,BUSINESS_COLLECTION);
        System.out.println(result);
        if (result.getMatchedCount()==0){
            throw new BBYException(StatusCode.NOT_FOUND,"收藏分组没找着");
        }
    }
    public void deleteUserFromGroup(String userId, String groupId,String value) throws BBYException {
        Bson query = Filters.eq("_id",new ObjectId(userId));
        Bson update = Updates.pull("userGroups.$[i].content",value);
        UpdateOptions updateOptions = new UpdateOptions().arrayFilters(
                Collections.singletonList(Filters.eq("i._id", groupId)));
        UpdateResult result = mongoTemplate.getCollection(BUSINESS_COLLECTION).updateOne(query,update,updateOptions);
        if (result.getMatchedCount()==0){
            throw new BBYException(StatusCode.NOT_FOUND,"收藏分组没找着");
        }
    }
    // 收藏
    private void checkFavoriteGroupName(String userId, String name) throws BBYException {
        Query query = new Query(where("_id").is(userId)
                .andOperator(where("favorites.name").is(name)));
        if (mongoTemplate.exists(query,BUSINESS_COLLECTION)){
            throw new BBYException(StatusCode.ALREADY_EXIST,"用户组已存在！");
        }
    }
    public void addFavoriteGroup(String userId, FavoriteGroup group) throws BBYException {
        checkFavoriteGroupName(userId,group.getName());
        Query query = new Query(where("_id").is(userId));
        Update update = new Update().addToSet("favorites",group);
        mongoTemplate.updateFirst(query,update,BUSINESS_COLLECTION);
    }
    public void deleteFavoriteGroup(String userId, String groupId) {
        Query query = new Query(where("_id").is(userId));
        Document doc = new Document();
        doc.put("_id",groupId);
        Update update = new Update().pull("favorites",doc);
        mongoTemplate.updateFirst(query,update,BUSINESS_COLLECTION);
    }
    public void renameFavoriteGroup(String userId, String groupId, String newName) throws BBYException {
        checkFavoriteGroupName(userId,newName);
        Query query = new Query(where("_id").is(userId)
                .andOperator(where("favorites._id").is(groupId)));
        if (!mongoTemplate.exists(query,BUSINESS_COLLECTION)){
            throw new BBYException(StatusCode.NOT_FOUND,"收藏分组没找着！");
        }
        Update update = new Update().set("favorites.$.name", newName);
        mongoTemplate.updateFirst(query,update,BUSINESS_COLLECTION);
    }
    public void addFavorite(String userId, String groupId, Favorite favorite) throws BBYException {
        Query query = new Query(where("_id").is(userId)
                .andOperator(where("favorites._id").is(groupId)));
        Query exist = new Query(where("_id").is(userId)
                .andOperator(where("favorites._id").is(groupId),
                        where("favorites.content.fileId").is(favorite.getFileId())));
        if (mongoTemplate.exists(exist,BUSINESS_COLLECTION)){
            throw new BBYException(StatusCode.FILE_ALREADY_EXIST,"该文件收藏已存在！");
        }
        Update update = new Update().push("favorites.$.content",favorite);
        UpdateResult result = mongoTemplate.updateFirst(query,update,BUSINESS_COLLECTION);
        if (result.getMatchedCount()==0){
            throw new BBYException(StatusCode.NOT_FOUND,"收藏分组没找着");
        }
    }
    public void deleteFavorite(String userId, String groupId,String fileId) {
        Bson query = Filters.eq("_id",new ObjectId(userId));
        Document doc = new Document();
        doc.put("fileId",fileId);
        Bson update = Updates.pull("favorites.$[i].content",doc);
        UpdateOptions updateOptions = new UpdateOptions().arrayFilters(
                Collections.singletonList(Filters.eq("i._id", groupId)));
        mongoTemplate.getCollection(BUSINESS_COLLECTION).updateOne(query,update,updateOptions);
    }

    public void renameFavorite(String userId, String groupId,String fileId,String newName) throws BBYException {
        Bson query = Filters.eq("_id",new ObjectId(userId));
        Bson update = Updates.set("favorites.$[i].content.$[j].name",newName);
        List<Bson> filters = new ArrayList<>();
        filters.add(Filters.eq("i._id", groupId));
        filters.add(Filters.eq("j.fileId", fileId));

        UpdateOptions updateOptions = new UpdateOptions().arrayFilters(filters);
        UpdateResult result = mongoTemplate.getCollection(BUSINESS_COLLECTION).updateOne(query,update,updateOptions);
        if (result.getModifiedCount()==0){
            throw new BBYException(StatusCode.NOT_FOUND,"未发现收藏记录");
        }
    }

    public UserSettings saveUserSettings(UserSettings settings) {
        return mongoTemplate.save(settings);
    }
    public UserSettings getUserSettings(String userId) {
        return mongoTemplate.findById(userId,UserSettings.class);
    }

    public void savePmMessage(PmMessage message) {
        mongoTemplate.save(message);
    }

    public PmMessage getPmMessage(String messageId) {
        return mongoTemplate.findById(messageId,PmMessage.class);
    }
}
